<template>
  <div
    ref="itemRef"
    class="item"
    :class="{
      'is-selected': isSelected,
      'is-focused': isFocused,
      'is-highlighted': isHighlighted || isHighlightedMultiple,
      'is-compact': snippetStore.compactMode
    }"
    :draggable="true"
    @click="onClickSnippet"
    @contextmenu="onClickContextMenu"
    @dragstart="onDragStart"
    @dragend="onDragEnd"
  >
    <div class="header">
      <div class="name">
        <div class="name__inner">
          <span>
            {{ name || 'Untitled snippet' }}
          </span>
          <span
            v-if="snippetStore.compactMode"
            class="date"
          >
            {{ dateFormat }}
          </span>
        </div>
      </div>
    </div>
    <div
      v-if="!snippetStore.compactMode"
      class="footer"
    >
      <div class="folder">
        {{ folder || 'Inbox' }}
      </div>
      <div class="date">
        {{ dateFormat }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ipc } from '@/electron'
import { track } from '@/services/analytics'
import { useFolderStore } from '@/store/folders'
import { useSnippetStore } from '@/store/snippets'
import type {
  ContextMenuRequest,
  ContextMenuResponse
} from '@shared/types/main'
import { onClickOutside, useClipboard } from '@vueuse/core'
import { computed, onUnmounted, ref } from 'vue'
import type { SystemFolderAlias } from '@shared/types/renderer/sidebar'
import { useTagStore } from '@/store/tags'
import { isToday, format } from 'date-fns'
import { emitter } from '@/composable'
import { useAppStore } from '@/store/app'

interface Props {
  id: string
  index: number
  name: string
  folder?: string
  date: number
}

const props = defineProps<Props>()

const snippetStore = useSnippetStore()
const folderStore = useFolderStore()
const tagStore = useTagStore()
const appStore = useAppStore()

const itemRef = ref()
const isFocused = ref(false)
const isHighlighted = ref(false)

const isSelected = computed(() => {
  if (snippetStore.selectedId) {
    return props.id === snippetStore.selectedId
  } else {
    return snippetStore.selectedMultiple?.some(i => i.id === props.id)
  }
})

const isHighlightedMultiple = computed(() => {
  if (snippetStore.selectedMultiple && snippetStore.isContextState) {
    return snippetStore.selectedMultiple?.some(i => i.id === props.id)
  }
  return false
})

onClickOutside(itemRef, () => {
  isFocused.value = false
  isHighlighted.value = false
})

const onClickSnippet = (e: MouseEvent) => {
  if (e.shiftKey) {
    if (snippetStore.selectedIndex > props.index) {
      snippetStore.selectedMultiple = snippetStore.snippetsByFilter.slice(
        props.index,
        snippetStore.selectedIndex + 1
      )
    } else {
      snippetStore.selectedMultiple = snippetStore.snippetsByFilter.slice(
        snippetStore.selectedIndex,
        props.index + 1
      )
    }
    snippetStore.selected = undefined
    isFocused.value = false
  } else {
    isFocused.value = true
    snippetStore.fragment = 0
    snippetStore.selectedMultiple = []
    snippetStore.getSnippetsById(props.id)
    tagStore.getTags()
    appStore.addToHistory(props.id)
  }
}

const onClickContextMenu = async () => {
  isHighlighted.value = true
  snippetStore.isContextState = true

  ipc.once('context-menu:close', () => {
    isHighlighted.value = false
    snippetStore.isContextState = false
  })

  const { action, data, type } = await ipc.invoke<
  ContextMenuRequest,
  ContextMenuResponse
  >('context-menu:snippet', {
    name: props.name,
    type: folderStore.selectedAlias ?? 'folder',
    selectedCount: snippetStore.selectedMultiple.length
  })

  const moveToTrash = async (alias?: SystemFolderAlias) => {
    if (snippetStore.selectedIds.length) {
      for (const id of snippetStore.selectedIds) {
        await snippetStore.patchSnippetsById(id, {
          isDeleted: true
        })
      }
    } else {
      await snippetStore.patchSnippetsById(props.id, {
        isDeleted: true
      })
    }
    if (!alias) {
      await snippetStore.getSnippetsByFolderIds(folderStore.selectedIds!)
      snippetStore.selected = snippetStore.snippets[0]
    } else {
      await snippetStore.getSnippets()
      snippetStore.setSnippetsByAlias(alias)
    }
  }

  if (action === 'delete') {
    if (type === 'folder') {
      await moveToTrash()
      track('snippets/move-to-trash')
    }

    if (type === 'favorites' || type === 'all' || type === 'inbox') {
      await moveToTrash(type)
    }

    if (type === 'trash') {
      if (snippetStore.selectedIds.length) {
        await snippetStore.deleteSnippetsByIds(snippetStore.selectedIds)
      } else {
        await snippetStore.deleteSnippetsById(props.id)
      }
      await snippetStore.getSnippets()
      snippetStore.setSnippetsByAlias(type)
    }
  }

  if (action === 'duplicate') {
    await snippetStore.duplicateSnippetById(props.id)
    track('snippets/duplicate')

    if (type === 'folder') {
      await snippetStore.getSnippetsByFolderIds(folderStore.selectedIds!)
    }

    if (type === 'all' || type === 'inbox') {
      await snippetStore.getSnippets()
      snippetStore.setSnippetsByAlias(type)
    }
  }

  if (action === 'favorites') {
    if (snippetStore.selectedIds.length) {
      for (const id of snippetStore.selectedIds) {
        await snippetStore.patchSnippetsById(id, {
          isFavorites: data
        })
      }
    } else {
      await snippetStore.patchSnippetsById(props.id, {
        isFavorites: data
      })
    }

    if (data) {
      track('snippets/add-to-favorites')
    } else {
      track('snippets/delete-from-favorites')
    }

    await snippetStore.getSnippets()

    if (type === 'favorites') {
      snippetStore.setSnippetsByAlias(type)
    }
  }

  if (action === 'restore-from-trash') {
    if (snippetStore.selectedIds.length) {
      for (const id of snippetStore.selectedIds) {
        await snippetStore.patchSnippetsById(id, {
          isDeleted: false
        })
      }
    } else {
      await snippetStore.patchSnippetsById(props.id, {
        isDeleted: false
      })
    }

    await snippetStore.getSnippets()
    snippetStore.setSnippetsByAlias('trash')
    track('snippets/restore-from-trash')
  }

  if (action === 'copy-snippet-link') {
    const { copy } = useClipboard({ source: `masscode://snippets/${props.id}` })
    copy()
    track('snippets/copy-link')
  }

  isHighlighted.value = false
  isFocused.value = false
  snippetStore.isContextState = false

  if (snippetStore.selectedIds.length) {
    snippetStore.selected = undefined
    snippetStore.selectedMultiple = []
  }
}

const dateFormat = computed(() => {
  const date = new Date(props.date)
  if (isToday(date)) return format(date, 'HH:mm')
  return format(date, 'dd.MM.yyyy')
})

const onDragStart = (e: DragEvent) => {
  if (snippetStore.selectedIds.length) {
    e.dataTransfer?.setData('payload', JSON.stringify(snippetStore.selectedIds))

    const count = snippetStore.selectedIds.length
    const el = document.createElement('div')
    const style = {
      padding: '2px 10px',
      backgroundColor: 'var(--color-bg)',
      borderRadius: '3px',
      color: 'var(--color-text)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      position: 'fixed',
      fontSize: '14px',
      top: '100%'
    }
    el.innerHTML = `${count} ${count > 1 ? 'items' : 'item'}`

    Object.assign(el.style, style)
    document.body.appendChild(el)

    e.dataTransfer?.setDragImage(el, 0, 0)
    setTimeout(() => el.remove(), 0)
  } else {
    e.dataTransfer?.setData('payload', JSON.stringify([props.id]))
  }
}

const onDragEnd = () => {
  folderStore.hoveredId = ''
}

const onScrollToSnippet = () => {
  if (snippetStore.selectedId !== props.id) {
    isFocused.value = false
  }
}

emitter.on('scroll-to:snippet', onScrollToSnippet)

onUnmounted(() => {
  emitter.off('scroll-to:snippet', onScrollToSnippet)
})
</script>

<style lang="scss" scoped>
.item {
  padding: var(--spacing-xs) var(--spacing-sm);
  position: relative;
  z-index: 2;
  user-select: none;
  &::after {
    content: '';
    height: 1px;
    background-color: var(--color-border);
    position: absolute;
    width: calc(100% - calc(var(--spacing-sm) * 2));
    bottom: 1px;
  }
  &.is-focused,
  &.is-selected,
  &.is-highlighted {
    &::before {
      content: '';
      position: absolute;
      top: 0px;
      left: 8px;
      right: 8px;
      bottom: 3px;
      border-radius: 5px;
      z-index: 1;
    }
  }
  &.is-focused {
    &::before {
      background-color: var(--color-primary) !important;
    }
    .name,
    .footer {
      color: #fff !important;
    }
  }
  &.is-selected {
    &::before {
      background-color: var(--color-snippet-selected);
    }
    .name,
    .footer {
      color: var(--color-text);
    }
  }
  &.is-highlighted {
    &::before {
      border-radius: 5px;
      outline: 2px solid var(--color-primary);
      outline-offset: -2px;
    }
  }
  &.is-compact {
    .date {
      color: var(--color-text-3);
      font-size: 11px;
      position: relative;
      top: 1px;
    }
  }
}
.name {
  display: table;
  table-layout: fixed;
  width: 100%;
  overflow: hidden;
  position: relative;
  z-index: 1;
  line-height: 24px;
  &__inner {
    display: flex;
    justify-content: space-between;
    gap: 4px;
    span {
      display: -webkit-box;
      -webkit-line-clamp: 1;
      -webkit-box-orient: vertical;
    }
  }
}
.footer {
  font-size: 11px;
  display: flex;
  position: relative;
  z-index: 1;
  justify-content: space-between;
  color: var(--color-text-3);
  padding-top: var(--spacing-sm);
}
</style>
